package com.hs.spp.ota;

import android.os.Handler;
import android.util.Log;

import com.chiemy.cardview.ColorLampFragment;
import com.chiemy.cardview.SPPOTAFragment;
import com.chiemy.cardview.Utils;

public class SPPTransProtocal {

	private final byte PROTOCOL_SOH =            0x01;    
	private final byte PROTOCOL_EOT =            0x04;
	private final byte PROTOCOL_ACK =            0x06;
	private final byte PROTOCOL_NAK =            0x15;
	private final byte PROTOCOL_CAN =            0x18;
	
	private final int RES_ERR_TRANSMIT           = -3;
	private final int RES_ERR_CANCEL             = -2;
	private final int RES_ERR_PARAM              = -1;
	private final int RES_OK                     = 0;
	
	private final int  PROTOCOL_ERROR_MAXNUMBER  = 0x200000;
	
	private final int PROTOCOL_PACKDATA_LEN =    1024;
	private final int PROTOCOL_PACKAGE_LEN  =   (PROTOCOL_PACKDATA_LEN + 4);
	private TransOverSpp hs_transfer = null;
	public SPPTransProtocal(TransOverSpp transfer){
		
		hs_transfer = transfer;
	}
	private int cal_checksum(byte[] ptr, int pos, int len)
	{
		int i,u32ChkSum = 0;

		for(i = 0; i < len; i++)
			u32ChkSum += ptr[i + pos];

		return u32ChkSum;
	}

	private void hs_packageData(byte[] pSrc, int pos, byte[] pPackage, byte cnt, int len)
	{
		Utils.java_memset(pPackage, 0, (byte) 0, PROTOCOL_PACKAGE_LEN);
		//memset(pPackage, 0, PROTOCOL_PACKAGE_LEN);

		pPackage[0] = PROTOCOL_SOH;
		pPackage[1] = cnt;
		pPackage[2] = (byte) ~cnt;

		//memcpy(&pPackage[3], pSrc, len);
		System.arraycopy(pSrc, pos, pPackage, 3, len);
		int chksum = cal_checksum(pPackage, 3, PROTOCOL_PACKDATA_LEN);
		pPackage[PROTOCOL_PACKAGE_LEN-1] = (byte) (chksum & 0xff);
		//pPackage[PROTOCOL_PACKAGE_LEN]   = (byte) ((chksum >> 8) & 0xff);
	}

	public int hs_transferData(byte[] pchPtr, int len, Handler handler)
	{
		int blkcnt, errCnt = 0;	
		//unsigned char dataBuf[PROTOCOL_PACKAGE_LEN];
		byte[] dataBuf = new byte[PROTOCOL_PACKAGE_LEN];
		long res;
		int packCnt;
		int pBufPtr;
		boolean resFlg;
		//char recData[10];
		byte[] recData = new byte[10];
		int transLen, leftLen = len;

		//memset((void *)pTransStatus, 0, sizeof(hs_backcall_para));

		blkcnt = len/PROTOCOL_PACKDATA_LEN;
		if(len % PROTOCOL_PACKDATA_LEN != 0)
			blkcnt ++;

		if(blkcnt == 0)
			return RES_ERR_PARAM;

		//pTransStatus->totalCnt = blkcnt;
		{
			//TODO init progressbar
			if(handler != null)
				handler.obtainMessage(SPPOTAFragment.MESSAGE_PBAR_INI, blkcnt, -1, null).sendToTarget();
		}

		do
		{
			if(SPPOTAFragment.mClassicConnected == false)
				return -3;
			res = hs_transfer.hs_read(recData, 0, 1, 1);
			if(res != 0)
				//return RES_ERR_TRANSMIT;
				continue;

			//TRACE("Transmit start? 0x%x\r\n", recData[0]);

			if(recData[0] != PROTOCOL_NAK)
			{
				errCnt ++;
				if(errCnt > PROTOCOL_ERROR_MAXNUMBER)
					return RES_ERR_TRANSMIT;

				continue;
			}

			pBufPtr = 0;
			packCnt = 1;
			errCnt = 0;
			
			
			do
			{
				if(leftLen >= PROTOCOL_PACKDATA_LEN)
					transLen = PROTOCOL_PACKDATA_LEN;
				else
					transLen = leftLen;

				if(handler != null)
					handler.obtainMessage(SPPOTAFragment.MESSAGE_UPDATE_PBAR, packCnt, -1, null).sendToTarget();
				hs_packageData(pchPtr, pBufPtr, dataBuf, (byte) packCnt, transLen);
				hs_transfer.hs_flush();
				res = hs_transfer.hs_write(dataBuf, PROTOCOL_PACKAGE_LEN);
				if(res != 0)
					return RES_ERR_TRANSMIT;

			//getRes:
				while(true)
				{
					resFlg = false;
					if(SPPOTAFragment.mClassicConnected == false)
						return -3;
					res = hs_transfer.hs_read(recData, 0, 1, 1);
					//TRACE("Transmit response result:0x%x, data: 0x%x\r\n", res, recData[0]);
					if(res != 0)
						return RES_ERR_TRANSMIT;
	
					if(recData[0] == (char)PROTOCOL_ACK)
					{
						pBufPtr += PROTOCOL_PACKDATA_LEN;
						Log.i("spp_xmodem", "cnt_num"+packCnt);
						packCnt ++;
	
						//pTransStatus->successCnt ++;
	
						leftLen -= transLen;
						errCnt = 0;
					}
					else if(recData[0] == (char)PROTOCOL_CAN)
					{
						res = hs_transfer.hs_read(recData, 0, 1, 1);
						if(res != 0)
							return RES_ERR_TRANSMIT;
	
						if(recData[0] == PROTOCOL_CAN)
							return RES_ERR_CANCEL;
					}
					else if(recData[0] == (char)PROTOCOL_NAK)
					{
						errCnt ++;
						//pTransStatus->totalErrCnt++;				
	
						//pTransStatus->lastErrIdx = packCnt;
						//pTransStatus->lastErrCnt = errCnt;
					}
					else
					{
						/* receive a error response */
						resFlg = true;
					}			
	
					if(resFlg == true)
						//goto getRes;
						continue ;
					else
						break;
				}
				//if(pTransStatus->successCnt == pTransStatus->totalCnt)
				if(leftLen <= 0)
				{
					int cc = 2;
					do
					{
						if(SPPOTAFragment.mClassicConnected == false)
							return -3;
						dataBuf[0] = PROTOCOL_EOT;
						//hs_transfer.hs_flush();
						res = hs_transfer.hs_write(dataBuf, 1);
						if(res != 0)
							return RES_ERR_TRANSMIT;

						res = hs_transfer.hs_read(recData, 0, 1, 0);
						
						if(res != 0)
							break;
							//return RES_ERR_TRANSMIT;
						
						cc--;
					}while(recData[0] != PROTOCOL_ACK && cc > 0);
					Log.i("SPPOTAFragment", "the end of Xmodem:"+recData[0]+"");
					//hs_transfer.hs_flush();
					return RES_OK;
				}

				if(errCnt > PROTOCOL_ERROR_MAXNUMBER)
					return RES_ERR_TRANSMIT;
			}while(true);
		}while(true);	

		//return RES_ERR_TRANSMIT;
	}

}
